package com.deep.bilibili.controller;


import cn.hutool.core.date.DateUtil;
import com.deep.bilibili.config.UploadConfig;
import com.deep.bilibili.constant.MimeTypeConstant;
import com.deep.bilibili.ffmpeg.FFmpegException;
import com.deep.bilibili.ffmpeg.FfmpegUtil;
import com.deep.bilibili.service.FileService;
import com.deep.bilibili.service.UploadService;
import com.deep.bilibili.util.Md5Util;
import com.deep.bilibili.util.RandomUtil;
import com.deep.bilibili.util.ResponseUtil;
import com.deep.bilibili.util.UploadUtil;
import com.deep.bilibili.vo.UploadFileVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.tomcat.jni.Directory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Api(tags = "上传管理")
@Controller
@RequestMapping("/admin/upload")
public class UploadController {

    private final Logger logger = LoggerFactory.getLogger(UploadController.class);

    @Autowired
    private UploadService uploadService;

    @Autowired
    private UploadConfig uploadConfig;

    @Autowired
    FileService fileService;

    @GetMapping("/index")
    public String index() {
        return "/upload/index";
    }


    /**
     * TODO 需要调整
     *
     * @return
     */
    private String getUploadPath() {
        String filePath = "assets" + File.separator + DateUtil.format(new Date(), "yyyy-MM-dd");
        return filePath;
    }

    /**
     * 上传文件
     *
     * @param file
     * @return
     */
    @ApiOperation(value = "上传文件")
    @ResponseBody
    @PostMapping("/file")
    public Object uploadFile(@RequestParam("file") MultipartFile file) {
        String filePath = getUploadPath();

        String fileName = file.getOriginalFilename();
        logger.info(" fileName = {}", fileName);

        String newFileName = Md5Util.getMd5(fileName) + fileName.substring(fileName.lastIndexOf("."), fileName.length());
        logger.info("newFileName = {}", newFileName);

        String uploadPath = uploadService.storeFile(file, filePath, newFileName);
        logger.info("uploadPath = {} ", uploadPath);

//        String fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath()
//                .path(filePath)
//                .path(fileName)
//                .toUriString();

        String fileDownloadUri = uploadConfig.getBaseUrl() + "/" + uploadPath.replaceAll("\\\\", "/");
        logger.info("fileDownloadUri = {}", fileDownloadUri);

        UploadFileVo uploadFileVo = new UploadFileVo(newFileName, fileDownloadUri,
                file.getContentType(), file.getSize());

        return ResponseUtil.ok(uploadFileVo);
    }


    /**
     * 上传图片
     *
     * @param file
     * @return
     */

    @ApiOperation(value = "上传图片")
    @ResponseBody
    @PostMapping("/pic")
    public Object uploadPic(@RequestParam("file") MultipartFile file) {
        // 限制图片类型
        String contentType = file.getContentType();

        if (null == contentType || !MimeTypeConstant.MIME_IMAGE.contains(contentType)) {

            return ResponseUtil.fail(50306, "图片文件类型不符！");
        }

        // 校验文件大小
        if (UploadUtil.checkFileSize(file.getSize(), 10, "M")) {
            logger.error("上传文件 {}", "文件大小超过限制！");

            return ResponseUtil.fail(50305, "文件大小超过限制！");
        }

        String filePath = getUploadPath();

        String fileName = file.getOriginalFilename();
        logger.info(fileName);
        String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length()).toLowerCase();
        if (null == fileExt || !MimeTypeConstant.EXT_IMAGE.contains(fileExt)) {
            return ResponseUtil.fail(50301, "图片文件格式错误");
        }


        String newFileName = Md5Util.getMd5(fileName) + "." + fileExt;
        logger.info("newFileName = {}", newFileName);

        String uploadPath = uploadService.storeFile(file, filePath, newFileName);
        logger.info("uploadPath = {}", uploadPath);

//        String fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath()
//                .path(filePath)
//                .path(fileName)
//                .toUriString();

        String fileDownloadUri = uploadConfig.getBaseUrl() + "/" + uploadPath.replaceAll("\\\\", "/");
        logger.info("fileDownloadUri = {}", fileDownloadUri);
        logger.info("上传图片");


        long fileSize = file.getSize();
        String mimeType = file.getContentType();

        UploadFileVo uploadFileVo = new UploadFileVo(
                newFileName, fileDownloadUri, mimeType, uploadPath, mimeType, fileSize
        );

        return ResponseUtil.ok(fileService.save(uploadFileVo));

    }

    @ApiOperation(value = "上传图片")
    @ResponseBody
    @PostMapping("/video")
    public Object uploadVideo(@RequestParam("file") MultipartFile file) throws FFmpegException {
        // 限制图片类型
        String contentType = file.getContentType();

        if (null == contentType || !MimeTypeConstant.MIME_VIDEO.contains(contentType)) {

            return ResponseUtil.fail(50306, "视频文件类型不符！");
        }

        // 校验文件大小
        if (UploadUtil.checkFileSize(file.getSize(), 500, "M")) {
            logger.error("上传文件 {}", "文件大小超过限制！");
            return ResponseUtil.fail(50305, "文件大小超过限制！");
        }

        String filePath = getUploadPath();

        String fileName = file.getOriginalFilename();
        logger.info(fileName);
        String fileExt = UploadUtil.getExtFromPath(fileName);

        if (null == fileExt || !MimeTypeConstant.EXT_VIDEO.contains(fileExt)) {
            return ResponseUtil.fail(50301, "视频文件格式错误");
        }


        String newFileName = Md5Util.getMd5(fileName) + "." + fileExt;
        logger.info("newFileName = {}", newFileName);

        String uploadPath = uploadService.storeFile(file, filePath, newFileName);
        logger.info("uploadPath = {}", uploadPath);

        String fullUploadPath = uploadService.getFullPath(uploadPath);

        String fileDownloadUri = uploadConfig.getBaseUrl() + "/" + uploadPath.replaceAll("\\\\", "/");
        logger.info("fileDownloadUri = {}", fileDownloadUri);
        logger.info("上传图片");


        long fileSize = file.getSize();
        String mimeType = file.getContentType();

        String coverPath = filePath + "/" + RandomUtil.randomString(8) + ".jpg";
        String fullCoverPath = fullUploadPath + "/" + RandomUtil.randomString(8) + ".jpg";
        String coverUrl = uploadConfig.getBaseUrl() + "/" + coverPath.replaceAll("\\\\", "/");
        boolean coverFlag = FfmpegUtil.cover(fullUploadPath, fullCoverPath);

        // 推流
        String streamName = RandomUtil.randomString(10);

        UploadFileVo uploadFileVo = new UploadFileVo(
                newFileName, fileDownloadUri, mimeType, uploadPath, mimeType, coverUrl, coverPath, streamName, fileSize
        );

        return ResponseUtil.ok(fileService.save(uploadFileVo));
    }

    /**
     * 多文件上传
     *
     * @param files
     * @return
     */
    @ApiOperation(value = "批量上传文件")
    @ResponseBody
    @PostMapping("/multipleFiles")
    public Object uploadMultipleFiles(@RequestParam("files") MultipartFile[] files) {
        List<Object> list = Arrays.stream(files)
                .map(this::uploadFile)
                .collect(Collectors.toList());

        return ResponseUtil.ok(list);
    }


    /**
     * 下载文件
     *
     * @param fileName
     * @param request
     * @return
     */
    @ApiOperation(value = "查询文件列表")
    @GetMapping("/down/{fileName:.+}")
    public ResponseEntity<Resource> downloadFile(@PathVariable String fileName, HttpServletRequest request) {
        // Load file as Resource
        Resource resource = uploadService.loadFileAsResource(fileName);

        // Try to determine file's content type
        String contentType = null;
        try {
            contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath());
        } catch (IOException ex) {
            logger.info("无法确定文件类型。");
        }

        // Fallback to the default content type if type could not be determined
        if (contentType == null) {
            contentType = "application/octet-stream";
        }

        return ResponseEntity.ok()
                .contentType(MediaType.parseMediaType(contentType))
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
                .body(resource);
    }


    /**
     * 上传文档文件
     *
     * @param file
     * @return
     */
    @ApiOperation(value = "上传文档")
    @PostMapping("/document")
    @ResponseBody
    public Object documentFile(@RequestParam("file") MultipartFile file) {
        String filePath = getUploadPath();

        String fileName = file.getOriginalFilename();
        logger.info(fileName);

        String newFileName = Md5Util.getMd5(fileName) + fileName.substring(fileName.lastIndexOf("."), fileName.length());
        logger.info("newFileName = {}", newFileName);

        String uploadPath = uploadService.storeFile(file, filePath, newFileName);
        logger.info("uploadPath = {}", uploadPath);

        String fileDownloadUri = uploadConfig.getBaseUrl() + "/" + uploadPath.replaceAll("\\\\", "/");
        logger.info("fileDownloadUri {}", fileDownloadUri);

        long fileSize = file.getSize();
        String mimeType = file.getContentType();

        // 使用原文件名
        UploadFileVo uploadFileVo = new UploadFileVo(
                fileName, fileDownloadUri, mimeType, uploadPath, mimeType, fileSize
        );

        return ResponseUtil.ok(fileService.save(uploadFileVo));
    }

}
